package ru.ifmo.trafficspy.analyzer.learning;

import java.util.List;

import ru.ifmo.trafficspy.analyzer.TrafficModel;
import ru.ifmo.trafficspy.analyzer.clustering.ClusterizerFactory;
import ru.ifmo.trafficspy.analyzer.clustering.KMeansClusterizer;
import ru.ifmo.trafficspy.analyzer.hmm.HiddenMarkovModel;
import ru.ifmo.trafficspy.common.Item;

public class TrafficModelFactory {
	public static TrafficModel getTrafficModel(List<Item> traffic, int packetClusterCnt, int intervalClusterCnt, int stateCnt, String description) {
		int n = traffic.size() / 2 + 1;
		double[] packets = new double[n];
		double[] intervals = new double[n - 1];
		{
			int i = 0;
			int i1 = 0;
			int i2 = 0;
			for (Item item : traffic) {
				if (i % 2 == 0) {
					packets[i1++] = item.getValue();
				} else {
					intervals[i2++] = item.getValue();
				}
				i++;
			}
		}
		KMeansClusterizer packetClusterizer = ClusterizerFactory.getKMeansClusterizer(packets, packetClusterCnt);
		KMeansClusterizer intervalClusterizer = ClusterizerFactory.getKMeansClusterizer(intervals, intervalClusterCnt);
		int[] actions = new int[2 * n - 1];
		{
			int i = 0;
			for (Item item : traffic) {
				if (i % 2 == 0) {
					actions[i] = packetClusterizer.getCluster(item.getValue());
				} else {
					actions[i] = packetClusterCnt + intervalClusterizer.getCluster(item.getValue());
				}
				i++;
			}
		}
		HiddenMarkovModel hmm = HiddenMarkovModel.getMostProbableModel(actions, packetClusterCnt + intervalClusterCnt, stateCnt, 1e-6);
		return new TrafficModel(hmm, packetClusterizer, intervalClusterizer, description);
	}

	public static TrafficModel getTrafficModel(List<Item> traffic, int packetClusterCnt, int intervalClusterCnt, int stateCnt, String description, double maxDist) {
		int n = traffic.size() / 2 + 1;
		double[] packets = new double[n];
		double[] intervals = new double[n - 1];
		{
			int i = 0;
			int i1 = 0;
			int i2 = 0;
			for (Item item : traffic) {
				if (i % 2 == 0) {
					packets[i1++] = item.getValue();
				} else {
					intervals[i2++] = item.getValue();
				}
				i++;
			}
		}
		KMeansClusterizer packetClusterizer = ClusterizerFactory.getKMeansClusterizer(packets, packetClusterCnt);
		KMeansClusterizer intervalClusterizer = ClusterizerFactory.getKMeansClusterizer(intervals, intervalClusterCnt);
		packetClusterizer.maxDist = maxDist;
		int[] actions = new int[2 * n - 1];
		{
			int i = 0;
			for (Item item : traffic) {
				if (i % 2 == 0) {
					actions[i] = packetClusterizer.getCluster(item.getValue());
				} else {
					actions[i] = packetClusterCnt + intervalClusterizer.getCluster(item.getValue());
				}
				i++;
			}
		}
		HiddenMarkovModel hmm = HiddenMarkovModel.getMostProbableModel(actions, packetClusterCnt + intervalClusterCnt, stateCnt, 1e-9);
		return new TrafficModel(hmm, packetClusterizer, intervalClusterizer, description);
	}
}
